/*
 * comm_objbase.h
 *
 *  Created on: 2010-1-7
 *      Author: gavinkwoe
 */

#ifndef COMM_OBJBASE_H_
#define COMM_OBJBASE_H_

#include "comm_features.h"
#include "comm_std.h"

/*************************************************************************
* MACRO
*************************************************************************/

#define COMM_INTERFACE_DECLARE( __name ) \
		struct __comm_vtbl_##__name

#define COMM_INTERFACE( __name, __ver ) \
		extern const unsigned char __comm_guid_##__name##__ver[]; \
		struct __comm_vtbl_##__name; \
		struct __comm_intf_##__name \
		{ \
			struct __comm_vtbl_##__name *	vptr; \
		}; \
		struct __comm_vtbl_##__name

#define COMM_INTERFACE_( __name, __ver, __parent ) \
		extern const unsigned char __comm_guid_##__name##__ver[]; \
		struct __comm_vtbl_##__name; \
		struct __comm_intf_##__name \
		{ \
			struct __comm_vtbl_##__name *	vptr; \
		}; \
		struct __comm_vtbl_##__name

#define COMM_METHOD( __method )					unsigned long	( COMM_PROC __method )
#define COMM_METHOD_( __ret, __method )			__ret			( COMM_PROC __method )

#define __COMM_INHERIT_FROM( __name )					struct __comm_vtbl_##__name	vtbl_##__name;

#define COMM_REF( __name )							struct __comm_intf_##__name *	
#define COMM_PREF( __name )						struct __comm_intf_##__name **

#define COMM_VTBL_TYPE( __name )					struct __comm_vtbl_##__name
#define COMM_VTBL( __name )						struct __comm_vtbl_##__name *	

#if defined(__cplusplus)
#define COMM_DECLARE_GUID( __name, __ver )			extern "C" const unsigned char __comm_guid_##__name##__ver[];
#else	// #if defined(__cplusplus)
#define COMM_DECLARE_GUID( __name, __ver )			extern const unsigned char __comm_guid_##__name##__ver[];
#endif	// #if defined(__cplusplus)

#define COMM_DEFINED_GUID( __name, __ver, __guid )	const unsigned char __comm_guid_##__name##__ver[] = __guid;
#define COMM_GUID( __name, __ver )					(comm_guid_t)__comm_guid_##__name##__ver

/*************************************************************************
* DECLARETION
*************************************************************************/

struct __struct_comm_coclass_desc;	// new-able class description
typedef struct __struct_comm_coclass_desc		comm_coclass_desc_t;
typedef struct __struct_comm_coclass_desc *	comm_coclass_desc_ptr_t;

/*************************************************************************
* DEFINITION
*************************************************************************/

struct __struct_comm_coclass_desc
{
	unsigned long	vtbl_size;
	unsigned char *	vtbl_funcs;
	unsigned long	priv_size;
};

/*************************************************************************
* INTERFACE
*************************************************************************/

COMM_INTERFACE( ICommO, 1 )
{
	// call by comm_obj_new
	COMM_METHOD( Construct )	( COMM_REF(ICommO) thiz, void * para );
	
	// call by comm_obj_delete
	COMM_METHOD( Destruct )	( COMM_REF(ICommO) thiz );
	
	COMM_METHOD( AddRef )		( COMM_REF(ICommO) thiz );
	COMM_METHOD( Release )		( COMM_REF(ICommO) thiz );
};

/*************************************************************************
* DECLARATION
*************************************************************************/

#if defined(__cplusplus)
extern "C" {
#endif	// #if defined(__cplusplus)

COMM_IMPORT void *				comm_obj_new( comm_coclass_desc_ptr_t desc, void * usr_data );
COMM_IMPORT void				comm_obj_delete( void * thiz );

#ifndef __COMM_FAST_OBJECT_ACCESS__
COMM_IMPORT unsigned char *	comm_obj_get_data( void * thiz );
COMM_IMPORT void *				comm_obj_get_vptr( void * thiz );
#endif	// #ifndef __COMM_FAST_OBJECT_ACCESS__

#if defined(__cplusplus)
}
#endif	// #if defined(__cplusplus)

/*************************************************************************
* MACRO
*************************************************************************/

#define COMM_TYPECAST( __ptr, __type )		( __type )( __ptr )
#define COMM_OBJECT( __ptr )				( COMM_REF(ICommO) )( __ptr )

#if defined(__COMM_FAST_OBJECT_ACCESS__)
#define COMM_GET_VTBL( p )			( *((unsigned long *)p) )
#define COMM_GET_VTBL_( p, t )		( (COMM_VTBL(t))COMM_GET_VTBL(p) )
#define COMM_GET_DATA( p )			( (unsigned char *)p + 4 )
#define COMM_GET_DATA_( p, t )		( (t)((unsigned char *)p + 4) )
#else	// #if defined(__COMM_FAST_OBJECT_ACCESS__)
#define COMM_GET_VTBL( p )			comm_obj_get_vptr( (void *)(p) )
#define COMM_GET_VTBL_( p, t )		( (COMM_VTBL(t))comm_obj_get_vptr( (void *)(p) ) )
#define COMM_GET_DATA( p )			comm_obj_get_data( (void *)(p) )
#define COMM_GET_DATA_( p, t )		( (t)comm_obj_get_data( (void *)(p) ) )
#endif	// #if defined(__COMM_FAST_OBJECT_ACCESS__)


#define ICommO_VTBL( p )			COMM_GET_VTBL_(p, ICommO)
#define ICommO_CALL( p, a )		ICommO_VTBL(p)->a
#define ICommO_AddRef( p )			ICommO_CALL( p, AddRef )( p )
#define ICommO_Release( p )		ICommO_CALL( p, Release )( p )

#define COMMO_HOLD( p )	( NULL == (p) ? 1 : ICommO_CALL(p, AddRef)( p ) )
#define COMMO_RELEASE( p )	( NULL == (p) ? 0 : ICommO_CALL(p, Release)( p ) )

#define COMMO_SAFE_RELEASE( p ) \
		if ( NULL != (p) ) \
		{ \
			ICommO_CALL(p, Release)( p ); \
			p = NULL; \
		}

#define COMMO_ASSIGN( a, b ) \
		if ( (void *)(a) != (void *)(b) ) \
		{ \
			COMMO_SAFE_RELEASE( a ); \
			(a) = (b); \
			COMMO_HOLD( a ); \
		}

#define COMMO_ASSIGN_AND_FREE( a, b ) \
		if ( (void *)(a) != (void *)(b) ) \
		{ \
			COMMO_SAFE_RELEASE( a ); \
			(a) = (b); \
			COMMO_HOLD( a ); \
			COMMO_SAFE_RELEASE( b ); \
		}

#endif /* COMM_OBJBASE_H_ */
